-module(chat_client).
-export([login/3, logout/0, who/0, say/2, say2all/1, client/3]).

login(IP, Port, Name) ->
    case whereis(client) of
        undefined ->
            register(client, spawn(chat_client, client, [IP, Port, Name]));
        _Other ->
            already_login
    end.

logout() ->
    case whereis(client) of
        undefined ->
            not_login;
        _Client ->
            client ! logout.

who() ->
    case whereis(client) of
        undefined ->
            not_login;
        _Client ->
            client ! who
    end.

say(To, Msg) ->
    case whereis(client) of
        undefined ->
            not_login;
        _Client ->
            client ! {say, To, Msg}
    end.

say2all(Msg) ->
    case whereis(client) of
        undefined ->
            not_login;
        _Client ->
            client ! {say2all, Msg}
    end.

client(IP, Port, Name) ->
    {ok, Socket} = gen_tcp:connect(IP, Port, [binary, {packet, 0}]),
    send(Socket, {login, Name}),
    recv(Socket),
    client(Socket).

client(Socket) ->
    receive
        logout ->
            send(Socket, logout),
            gen_tcp:close(Socket),
            exit(normal);
        who ->
            send(Socket, who),
            recv(Socket);
        {say, To, Msg} ->
            send(Socket, {say, To, Msg}),
            recv(Socket);
        {say2all, Msg} ->
            send(Socket, {say2all, Msg});
        {tcp, Socket, Bin} ->
            case binary_to_term(Bin) of
                {msg, From, Msg} ->
                    io:format("Received msg from ~p: ~p~n", [From, Msg])
            end
    end,
    client(Socket).

send(Socket, Msg) ->
    gen_tcp:send(Socket, term_to_binary(Msg)).

recv(Socket) ->
    receive 
        {tcp, Socket, Bin} ->
            case binary_to_term(Bin) of
                {ok, What} ->
                    io:format("~p~n", [What]);
                {error, Why} ->
                    io:format("~p~n", [Why]),
                    exit(normal)
            end
    end.
